/**
 * SwarmInterface.java
 * Created: 11.03.2011, 14:04:59
 */
package model;

import java.util.ArrayList;
import model.PlayerColor;
import model.ds.PieceType;
import model.HexDirection;
import common.Tuple;

/**
 * An interface defining the methods that have to be implemented by a swarm
 * model that should be used by the {@code JSwarmArea} user interface.
 * @author Jan-Philipp Kappmeier
 */
public interface SwarmInterface {
	/**
	 * Introduces the first piece (which is of the white player, who always
	 * starts the game) to the game.
	 * @param pieceType the type of the first piece
	 */
	public void introduce( PieceType pieceType );

	/**
	 * Introduces the first piece for the black player (which has to be adjacent
	 * to the first (white) piece).
	 * @param pieceType the type of the first black piece
	 * @param hexDirection the relative position of the piece to the first white piece
	 */
	public void introduce( PieceType pieceType, HexDirection hexDirection );

		/**
	 * <p>Introduces a piece to the game (for the current player). The position is
	 * specified relatively to some other piece already introduced to the game.</p>
	 * <p>The anchor piece is specified by an index which is in the range of
	 * {@code [0,#introduced-1]}. The direction is then specified relatively to
	 * this piece.</p>
	 * @param pieceType the type of the piece that is introduced
	 * @param anchorPiece the index (starting with 0) of the piece used as anchor
	 * @param hexDirection the relative position of the new piece to the anchor piece
	 */
	public void introduce( PieceType pieceType, int anchorPiece, HexDirection hexDirection );

	/**
	 * <p>Moves a piece. As for introduction the target position is specified
	 * relatively to an arbitrary piece (which must be a neighbor of the new
	 * position).</p>
	 * <p>Both pieces are specified by its index, starting with 0.</p>
	 * @param piece the index of the piece that is moved
	 * @param anchorPiece the index of the anchor piece
	 * @param hexDirection the direction relatively to the anchor piece
	 */
	public void move( int piece, int anchorPiece, HexDirection hexDirection );

	/**
	 * <p>Returns a list of fields on which the current player can introduce new
	 * pieces.</p>
	 * <p>The list contains {@link Tuple}s of an integer value and a
	 * {@link HexDirection}. Each tuple denotes a field that is adjacent to a
	 * field that already contains a piece. The integer number denotes the
	 * piece (in the range {@code [0,#introduced-1]}). The second value is the
	 * direction in which the field lies.</p>
	 * @return a list of possible fields for introduction
	 */
	public ArrayList<Tuple<Integer,HexDirection>> getIntroduceable();

	/**
	 * <p>Returns a list of fields which are reachable by a piece.</p>
	 * <p>The list contains {@link Tuple}s of an integer value and a
	 * {@link HexDirection}. Each tuple denotes a field that is adjacent to a
	 * field that already contains a piece. The integer number denotes the
	 * piece (in the range {@code [0,#introduced-1]}). The second value is the
	 * direction in which the field lies.</p>
	 * @param pieceIndex the index of the piece
	 * @return a list of fields reachable by the piece
	 */
	public ArrayList<Tuple<Integer,HexDirection>> getReachable( int pieceIndex );

	/**
	 * Returns the type of piece (defined by its id).
	 * @param pieceIndex the index of the piece
	 * @return the type of the piece
	 */
	public PieceType getPieceType( int pieceIndex );

	/**
	 * Returns the number of remaining pieces of a given type for a given player.
	 * @param player the player
	 * @param type the piece type
	 * @return returns the number of remaining pieces for the player
	 */
	public int getRemainingPieces( PlayerColor player, PieceType type );

	/**
	 * Returns the total number of pieces already introduced.
	 * @return the total number of pieces already introduced
	 */
	public int getIntroducedPieces();

	/**
	 * Returns the player whose turn it is.
	 * @return the player whose turn it is
	 */
	public PlayerColor getCurrentPlayer();

	/**
	 * Decides whether the game is over, or not.
	 * @return {@code true} if the game is over, {@code false} otherwise
	 */
	public boolean isGameOver();
}
